const { PointRule, PointTransaction, SystemLog } = require('../models');
const { AppError } = require('../middlewares/errorHandler');
const { logger } = require('../utils/logger');
const { Op } = require('sequelize');

class PointRuleController {
  /**
   * 创建积分规则
   * @param {Object} ctx - 上下文
   * @returns {Promise<void>}
   */
  async createPointRule(ctx) {
    const {
      name,
      type,
      points,
      conditions,
      description,
      validFrom,
      validTo,
      dailyLimit,
      monthlyLimit
    } = ctx.request.body;
    const userId = ctx.state.user.id;

    // Check if rule name already exists
    const existingRule = await PointRule.findOne({ where: { name } });
    if (existingRule) {
      throw new AppError(400, 'Point rule name already exists');
    }

    // Create point rule
    const pointRule = await PointRule.create({
      name,
      type,
      points,
      conditions,
      description,
      validFrom,
      validTo,
      dailyLimit,
      monthlyLimit,
      status: 'active'
    });

    // 记录操作日志
    await SystemLog.create({
      type: 'operation',
      action: 'create_point_rule',
      userId,
      ipAddress: ctx.ip,
      userAgent: ctx.headers['user-agent'],
      description: `Point rule created: ${name}`
    });

    ctx.status = 201;
    ctx.body = {
      status: 'success',
      data: { pointRule }
    };
  }

  /**
   * 更新积分规则
   * @param {Object} ctx - 上下文
   * @returns {Promise<void>}
   */
  async updatePointRule(ctx) {
    const { id } = ctx.params;
    const {
      name,
      type,
      points,
      conditions,
      description,
      validFrom,
      validTo,
      dailyLimit,
      monthlyLimit,
      status
    } = ctx.request.body;
    const userId = ctx.state.user.id;

    const pointRule = await PointRule.findByPk(id);
    if (!pointRule) {
      throw new AppError(404, 'Point rule not found');
    }

    // 检查新名称是否已存在
    if (name && name !== pointRule.name) {
      const existingRule = await PointRule.findOne({ where: { name } });
      if (existingRule) {
        throw new AppError(400, 'Point rule name already exists');
      }
    }

    // 更新积分规则
    await pointRule.update({
      name,
      type,
      points,
      conditions,
      description,
      validFrom,
      validTo,
      dailyLimit,
      monthlyLimit,
      status
    });

    // 记录操作日志
    await SystemLog.create({
      type: 'operation',
      action: 'update_point_rule',
      userId,
      ipAddress: ctx.ip,
      userAgent: ctx.headers['user-agent'],
      description: `Point rule updated: ${pointRule.name}`
    });

    ctx.body = {
      status: 'success',
      data: { pointRule }
    };
  }

  /**
   * 删除积分规则
   * @param {Object} ctx - 上下文
   * @returns {Promise<void>}
   */
  async deletePointRule(ctx) {
    const { id } = ctx.params;
    const userId = ctx.state.user.id;

    const pointRule = await PointRule.findByPk(id);
    if (!pointRule) {
      throw new AppError(404, 'Point rule not found');
    }

    // 检查规则是否有任何交易
    const transactionCount = await PointTransaction.count({ where: { ruleId: id } });
    if (transactionCount > 0) {
      throw new AppError(400, 'Cannot delete point rule with existing transactions');
    }

    await pointRule.destroy();

    // 记录操作日志
    await SystemLog.create({
      type: 'operation',
      action: 'delete_point_rule',
      userId,
      ipAddress: ctx.ip,
      userAgent: ctx.headers['user-agent'],
      description: `Point rule deleted: ${pointRule.name}`
    });

    ctx.body = {
      status: 'success',
      message: 'Point rule deleted successfully'
    };
  }

  /**
   * 获取积分规则列表
   * @param {Object} ctx - 上下文
   * @returns {Promise<void>}
   */
  async getPointRules(ctx) {
    const { type, status } = ctx.query;
    const where = {};

    if (type) where.type = type;
    if (status) where.status = status;

    const pointRules = await PointRule.findAll({
      where,
      order: [['createdAt', 'DESC']]
    });

    ctx.body = {
      status: 'success',
      data: { pointRules }
    };
  }

  /**
   * 获取单个积分规则
   * @param {Object} ctx - 上下文
   * @returns {Promise<void>}
   */
  async getPointRule(ctx) {
    const { id } = ctx.params;

    const pointRule = await PointRule.findByPk(id, {
      include: [{
        model: PointTransaction,
        attributes: ['id', 'userId', 'points', 'type', 'status', 'createdAt'],
        limit: 10,
        order: [['createdAt', 'DESC']]
      }]
    });

    if (!pointRule) {
      throw new AppError(404, 'Point rule not found');
    }

    ctx.body = {
      status: 'success',
      data: { pointRule }
    };
  }

  /**
   * 更新积分规则状态
   * @param {Object} ctx - 上下文
   * @returns {Promise<void>}
   */
  async updatePointRuleStatus(ctx) {
    const { id } = ctx.params;
    const { status } = ctx.request.body;
    const userId = ctx.state.user.id;

    const pointRule = await PointRule.findByPk(id);
    if (!pointRule) {
      throw new AppError(404, 'Point rule not found');
    }

    await pointRule.update({ status });

    // 记录操作日志
    await SystemLog.create({
      type: 'operation',
      action: 'update_point_rule_status',
      userId,
      ipAddress: ctx.ip,
      userAgent: ctx.headers['user-agent'],
      description: `Point rule ${pointRule.name} status updated to ${status}`
    });

    ctx.body = {
      status: 'success',
      data: { pointRule }
    };
  }

  /**
   * 获取活动积分规则
   * @param {Object} ctx - 上下文
   * @returns {Promise<void>}
   */
  async getActiveRules(ctx) {
    const now = new Date();
    const pointRules = await PointRule.findAll({
      where: {
        status: 'active',
        [Op.and]: [
          {
            [Op.or]: [
              { validFrom: null },
              { validFrom: { [Op.lte]: now } }
            ]
          },
          {
            [Op.or]: [
              { validTo: null },
              { validTo: { [Op.gte]: now } }
            ]
          }
        ]
      }
    });

    ctx.body = {
      status: 'success',
      data: { pointRules }
    };
  }

  /**
   * 获取积分规则使用统计
   * @param {Object} ctx - 上下文
   * @returns {Promise<void>}
   */
  async getRuleUsageStats(ctx) {
    const { id } = ctx.params;
    const { startDate, endDate } = ctx.query;

    const pointRule = await PointRule.findByPk(id);
    if (!pointRule) {
      throw new AppError(404, 'Point rule not found');
    }

    const where = {
      ruleId: id,
      status: 'completed'
    };

    if (startDate && endDate) {
      where.createdAt = {
        [Op.between]: [new Date(startDate), new Date(endDate)]
      };
    }

    const stats = await PointTransaction.findAll({
      where,
      attributes: [
        [sequelize.fn('COUNT', sequelize.col('id')), 'totalTransactions'],
        [sequelize.fn('SUM', sequelize.col('points')), 'totalPoints'],
        [sequelize.fn('COUNT', sequelize.fn('DISTINCT', sequelize.col('userId'))), 'uniqueUsers']
      ]
    });

    ctx.body = {
      status: 'success',
      data: { stats: stats[0] }
    };
  }
}

module.exports = new PointRuleController(); 